package com.pdemo.front.filter;

import java.io.IOException;
import java.security.Principal;

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.ext.Provider;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import com.pdemo.front.annotation.Authenticate;
import com.pdemo.front.service.AdminService;


@Provider
@Priority(Priorities.AUTHENTICATION)
@Authenticate
public class AuthenticationFilter implements ContainerRequestFilter
{
	
	final static Logger logger = LogManager.getLogger(AuthenticationFilter.class);

	@Autowired
	private AdminService adminService;
	
	@Override
	public void filter(ContainerRequestContext requestContext) throws IOException
	{
		if (!authenticate(requestContext))
		{
			abort(requestContext);
		}
	}

	private boolean authenticate(ContainerRequestContext requestContext)
	{
		Token token = getTokenFromHeader(requestContext.getHeaders());
		if (token == null) {
			logger.warn("miss username or password");
			return false;
		}
		final ApplicationPrincipal principal =  adminService.authenticate(token);
		if(principal == null || !principal.getEnabled()) return false;
		requestContext.setSecurityContext(new SecurityContext(){
			@Override
			public Principal getUserPrincipal() {
				return principal;
			}

			@Override
			public boolean isUserInRole(String role) {
				return principal.isUserInRole(role);
			}

			@Override
			public boolean isSecure() {
				return true;
			}

			@Override
			public String getAuthenticationScheme() {
				return null;
			}
			
		});
		return true;
	
	}

	private Token getTokenFromHeader(MultivaluedMap<String, String> headers)
	{
		if (headers == null) return null;
		String mobile = headers.getFirst(Token.MOBILE);
		String token = headers.getFirst(Token.TOKEN);
		if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(token)) return null;
		return new Token(mobile.trim(), token.trim());
	}

	

	private void abort(ContainerRequestContext requestContext)
	{
		requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("invalid token.").build());
	}
}
